home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 April / EnigmA AMIGA RUN 17 (1997)(G.R. Edizioni)(IT)[!][issue 1997-04][EAR-CD].iso / EARCD / text / hyper / hsc_source.lha / hsc / source / hsclib / deftag.c < prev    next >
C/C++ Source or Header  |  1996-11-25  |  18KB  |  675 lines

  1. /*
  2.  * hsclib/deftag.c
  3.  *
  4.  * define new tag from input file
  5.  *
  6.  * Copyright (C) 1995,96  Thomas Aglassinger
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  *
  22.  * updated: 25-Nov-1996
  23.  * created: 13-Oct-1995
  24.  */
  25.  
  26. #include "hsclib/inc_base.h"
  27.  
  28. #include "hsclib/defattr.h"
  29. #include "hsclib/eval.h"
  30. #include "hsclib/input.h"
  31. #include "hsclib/skip.h"
  32.  
  33. /*
  34.  * get_mci
  35.  *
  36.  */
  37. LONG get_mci(HSCPRC * hp)
  38. {
  39.     hp->tag_call_id++;
  40.  
  41.     return (hp->tag_call_id);
  42. }
  43.  
  44. /*
  45.  * unget_mci
  46.  *
  47.  */
  48. VOID unget_mci(HSCPRC * hp)
  49. {
  50.     hp->tag_call_id--;
  51.     if (hp->tag_call_id < 0)
  52.     {
  53.         panic("MCI underflow");
  54.     }
  55. }
  56.  
  57. /*
  58.  * get_current_mci
  59.  *
  60.  */
  61. LONG get_current_mci(HSCPRC * hp)
  62. {
  63.     return (hp->tag_call_id);
  64. }
  65.  
  66. /*
  67.  *-------------------------------------
  68.  * define a new tag from input file
  69.  *-------------------------------------
  70.  */
  71.  
  72. /*
  73.  * def_tag_name
  74.  *
  75.  */
  76. HSCTAG *def_tag_name(HSCPRC * hp, BOOL * open_tag)
  77. {
  78.     STRPTR nw = NULL;
  79.     HSCTAG *tag = NULL;
  80.     DLLIST *taglist = hp->deftag;
  81.  
  82.     /* get tag name */
  83.     nw = infget_tagid(hp);
  84.  
  85.     /* create new tag */
  86.     if (nw)
  87.     {
  88.         *open_tag = (BOOL) (strcmp(nw, "/"));
  89.         if (!(*open_tag))
  90.         {
  91.             /* add closing tag */
  92.             nw = infget_tagid(hp);
  93.             if (nw)
  94.             {
  95.                 tag = find_strtag(taglist, nw);
  96.                 if (tag)
  97.                     /* set closing flag */
  98.                     tag->option |= HT_CLOSE;
  99.                 else
  100.                 {
  101.                     hsc_message(hp, MSG_DEFTAG_NO_OPEN,
  102.                                 "no start tag for %c", nw);
  103.                 }
  104.             }                   /* err_eof already called in infget_tagid() */
  105.         }
  106.         else
  107.         {
  108.             tag = find_strtag(taglist, nw);
  109.             if (tag)
  110.             {
  111.                 /* find tag-node in list to delete it
  112.                  * NOTE: this is rather stupid, 'cause the list
  113.                  * has to be searched twice this way; but who cares? */
  114.                 DLNODE *nd = find_dlnode(hp->deftag->first,
  115.                                          (APTR) nw, cmp_strtag);
  116.  
  117.                 /* new tag/macro replaces old tag/macro */
  118.                 tag->occured = FALSE;
  119.  
  120.                 hsc_message(hp, MSG_REDEFINE_TAG, "redefined %T", tag);
  121.  
  122.                 del_dlnode(hp->deftag, nd);
  123.  
  124.             }
  125.  
  126.             /* create a new opening tag */
  127.             tag = app_tag(taglist, nw);
  128.         }
  129.     }                           /* err_eof already called in infget_tagid() */
  130.  
  131.     /* convert tag name to upper  case */
  132.     if (tag)
  133.         upstr(tag->name);
  134.  
  135.     return (tag);
  136. }
  137.  
  138. /*
  139.  * check_tag_option
  140.  *
  141.  * check if a tag-option-string is equal to an id/short id.
  142.  * if so, set the corresponding option value within the tag.
  143.  *
  144.  * params: option..option string to check for (read from input)
  145.  *         tag.....tag to update option value for
  146.  *         id......id string of option (eg "REQUIRED")
  147.  *         sid.....short id string (eg "REQ")
  148.  *         value...option value to OR with old tag's option value
  149.  * result: TRUE, if tag's option value updated
  150.  */
  151. static BOOL check_tag_option(HSCPRC * hp, STRPTR option, HSCTAG * tag,
  152.                              STRPTR id, STRPTR sid, ULONG value)
  153. {
  154.     BOOL found = FALSE;
  155.  
  156.     if (!((upstrcmp(option, id)) && (upstrcmp(option, sid))))
  157.     {
  158.         DDT(fprintf(stderr, DHL "  option %s\n", id));
  159.         tag->option |= value;
  160.         found = TRUE;
  161.     }
  162.  
  163.     return (found);
  164.  
  165. }
  166.  
  167. /*
  168.  * parse_lazy_option
  169.  *
  170.  * allowed abbrevations:
  171.  *
  172.  * c  CLASS:string
  173.  * h  HREF:uri
  174.  * i  ID:id
  175.  * k  CLEAR:enum("left|right|all|*")
  176.  * l  LANG:string
  177.  * m  MD:string
  178.  * s  SRC:URI
  179.  * w  NOWRAP:bool
  180.  */
  181. static HSCATTR *def_lazy_attr(HSCPRC * hp, HSCTAG * tag,
  182.                               STRPTR attrname, BYTE attrtype)
  183. {
  184.     HSCATTR *newattr = app_var(tag->attr, attrname);
  185.     DDA(fprintf(stderr, DHL "new attr: `%s'\n", attrname));
  186.     newattr->vartype = attrtype;
  187.     return (newattr);
  188. }
  189.  
  190. static BOOL parse_lazy_option(HSCPRC * hp, HSCTAG * tag, STRPTR lazy)
  191. {
  192.     BOOL ok = TRUE;
  193.  
  194.     while (lazy[0])
  195.     {
  196.         switch (lazy[0])
  197.         {
  198.         case 'c':
  199.             def_lazy_attr(hp, tag, "CLASS", VT_STRING);
  200.             break;
  201.         case 'h':
  202.             def_lazy_attr(hp, tag, "HREF", VT_URI);
  203.             break;
  204.         case 'i':
  205.             def_lazy_attr(hp, tag, "ID", VT_ID);
  206.             break;
  207.         case 'k':
  208.             {
  209.                 HSCATTR *clear_attr =
  210.                 def_lazy_attr(hp, tag, "CLEAR", VT_ENUM);
  211.                 clear_attr->enumstr = strclone("left|right|all|*");
  212.             }
  213.             break;
  214.         case 'l':
  215.             def_lazy_attr(hp, tag, "LANG", VT_STRING);
  216.             break;
  217.         case 'm':
  218.             def_lazy_attr(hp, tag, "MD", VT_STRING);
  219.             break;
  220.         case 's':
  221.             def_lazy_attr(hp, tag, "SRC", VT_URI);
  222.             break;
  223.         case 'w':
  224.             def_lazy_attr(hp, tag, "NOWRAP", VT_BOOL);
  225.             break;
  226.         default:
  227.             hsc_message(hp, MSG_UNKN_TAG_OPTION,
  228.                         "unknown tag modifier %q (arg %q)",
  229.                         "LAZY", ch2str(lazy[0]));
  230.             break;
  231.         }
  232.         lazy++;
  233.     }
  234.  
  235.     return (ok);
  236. }
  237.  
  238. /*
  239.  * parse_tag_option
  240.  */
  241. static BOOL parse_tag_option(HSCPRC * hp, STRPTR option, HSCTAG * tag)
  242. {
  243.     BOOL ok = FALSE;
  244.     HSCATTR *attr = new_hscattr(PREFIX_TMPATTR "mbi.naw");
  245.  
  246.     attr->vartype = VT_STRING;
  247.  
  248.     if (!(upstrcmp(option, TO_MBI_STR)
  249.           && upstrcmp(option, TO_MBI_SHT)))
  250.     {                           /* must be inside */
  251.         if (parse_eq(hp))
  252.         {
  253.             STRPTR strmbi = eval_expression(hp, attr, NULL);
  254.  
  255.             if (strmbi)
  256.             {
  257.                 tag->mbi = strclone(strmbi);
  258.                 DDT(fprintf(stderr, DHL "  mbi = `%s'\n", tag->mbi));
  259.                 ok = TRUE;
  260.             }
  261.         }
  262.     }
  263.     else if (!(upstrcmp(option, TO_NAW_STR)
  264.                && upstrcmp(option, TO_NAW_SHT)))
  265.     {                           /* not allowed with */
  266.         if (parse_eq(hp))
  267.         {
  268.             STRPTR strnaw = eval_expression(hp, attr, NULL);
  269.  
  270.             if (strnaw)
  271.             {
  272.                 tag->naw = strclone(strnaw);
  273.                 DDT(fprintf(stderr, DHL "  mbi = `%s'\n", tag->naw));
  274.                 ok = TRUE;
  275.             }
  276.         }
  277.     }
  278.     else if (!(upstrcmp(option, TO_LAZY_STR)
  279.                && upstrcmp(option, TO_LAZY_SHT)))
  280.     {                           /* lazy standard attribs */
  281.         if (parse_eq(hp))
  282.         {
  283.             STRPTR strlazy = eval_expression(hp, attr, NULL);
  284.  
  285.             if (strlazy)
  286.             {
  287.                 DDT(fprintf(stderr, DHL "  lazy= `%s'\n", strlazy));
  288.                 ok = parse_lazy_option(hp, tag, strlazy);
  289.             }
  290.         }
  291.     }
  292.     else
  293.     {
  294.         ok |= check_tag_option(hp, option, tag, TO_CLOSE_STR, TO_CLOSE_SHT, HT_CLOSE);
  295.         ok |= check_tag_option(hp, option, tag, TO_SPECIAL_STR, TO_SPECIAL_SHT, HT_SPECIAL);
  296.         ok |= check_tag_option(hp, option, tag, TO_JERK_STR, TO_JERK_SHT, HT_JERK);
  297.         ok |= check_tag_option(hp, option, tag, TO_AUTOCLOSE_STR, TO_AUTOCLOSE_SHT, HT_AUTOCLOSE);
  298.         ok |= check_tag_option(hp, option, tag, TO_OBSOLETE_STR, TO_OBSOLETE_SHT, HT_OBSOLETE);
  299.         ok |= check_tag_option(hp, option, tag, TO_ONLYONCE_STR, TO_ONLYONCE_SHT, HT_ONLYONCE);
  300.         ok |= check_tag_option(hp, option, tag, TO_REQUIRED_STR, TO_REQUIRED_SHT, HT_REQUIRED);
  301.         ok |= check_tag_option(hp, option, tag, TO_SKIPLF_STR, TO_SKIPLF_SHT, HT_SKIPLF);
  302.         ok |= check_tag_option(hp, option, tag, TO_WHTSPC_STR, TO_WHTSPC_SHT, HT_WHTSPC);
  303.  
  304.         if (!ok)
  305.         {
  306.             hsc_message(hp, MSG_UNKN_TAG_OPTION,
  307.                         "unknown tag modifer %q", option);
  308.         }
  309.     }
  310.  
  311.     /* remove temp. attribute */
  312.     del_hscattr(attr);
  313.  
  314.     return (ok);
  315. }
  316.  
  317. /*
  318.  * parse_tag_var
  319.  */
  320. static BOOL parse_tag_var(HSCPRC * hp, HSCTAG * tag)
  321. {
  322.     BOOL ok = FALSE;
  323.     HSCATTR *var = NULL;
  324.  
  325.     /* define new attribute */
  326.     var = define_var(hp, tag->attr, VF_CONST | VF_GLOBAL);
  327.  
  328.     /* set several values of tag structure, if attribute has
  329.      * some special flags set
  330.      */
  331.     if (var)
  332.     {
  333.         /* attribute is uri that tells the size */
  334.         if (var->varflag & VF_GETSIZE)
  335.             tag->uri_size = var;
  336.  
  337.         /* attribute is uri that tells if the tag should be stripped */
  338.         if (var->varflag & VF_STRIPEXT)
  339.             tag->uri_stripext = var;
  340.  
  341.         /* set attribute flag to keep quotes */
  342.         if (tag->option & HT_KEEP_QUOTES)
  343.             var->varflag |= VF_KEEP_QUOTES;
  344.  
  345.         /* set macro attribute flag for macro tags */
  346.         if (tag->option & HT_MACRO)
  347.             var->varflag |= VF_MACRO;
  348.  
  349.         ok = TRUE;
  350.     }
  351.  
  352.     return (ok);
  353. }
  354.  
  355. /*
  356.  * def_tag_args
  357.  *
  358.  */
  359. BOOL def_tag_args(HSCPRC * hp, HSCTAG * tag)
  360. {
  361.     BOOL ok = FALSE;
  362.     STRPTR nw;
  363.     INFILE *inpf = hp->inpf;
  364.  
  365.     if (tag)
  366.     {
  367.         ok = TRUE;
  368.  
  369.         /* read args */
  370.         nw = infgetw(inpf);
  371.  
  372.         /*
  373.          * set tag options
  374.          */
  375.         while (nw && ((!strcmp(nw, "/")) || !strcmp(nw, "\n")))
  376.         {
  377.             nw = infgetw(inpf);
  378.             if (nw)
  379.             {
  380.                 if (strcmp(nw, "\n"))
  381.                     ok &= parse_tag_option(hp, nw, tag);
  382.                 nw = infgetw(inpf);
  383.             }
  384.         }
  385.  
  386.         /* auto-set HT_KEEP_QUOTES */
  387.         if (!strncmp(tag->name, HSC_TAGID, strlen(HSC_TAGID)))
  388.             tag->option |= HT_KEEP_QUOTES;
  389.  
  390.         /*
  391.          * set tag attributes
  392.          */
  393.         while (nw && ((strcmp(nw, ">") || !strcmp(nw, "\n"))))
  394.         {
  395.             if (strcmp(nw, "\n"))
  396.             {
  397.                 inungetcw(inpf);
  398.                 ok &= parse_tag_var(hp, tag);
  399.             }
  400.  
  401.             nw = infgetw(inpf);
  402.         }
  403.  
  404.         /* skip linefeeds */
  405.         while (nw && !strcmp(nw, "\n"))
  406.             nw = infgetw(inpf);
  407.  
  408.         /* check for ">" at end */
  409.         if (nw)
  410.         {
  411.             inungetcw(inpf);
  412.             ok = parse_gt(hp);
  413.         }
  414.     }
  415.  
  416.     return (ok);
  417. }
  418.  
  419. /*
  420.  * set_tag_arg
  421.  *
  422.  * parse & set one single tag argument
  423.  *
  424.  */
  425. static BOOL set_tag_arg(HSCPRC * hp, DLLIST * varlist, STRPTR varname, BOOL unknown)
  426. {
  427.     HSCATTR *var = find_varname(varlist, varname);
  428.     INFILE *inpf = hp->inpf;
  429.     STRPTR arg = NULL;
  430.     BOOL ok = FALSE;
  431.     BOOL inheritage_failed = FALSE;     /* flag: set, if "?=" failed */
  432.     STRPTR nw;
  433.     HSCATTR skipvar;            /* dummy-attribute to skip unknown */
  434.     EXPSTR *attr_str = init_estr(40);   /* string for attribute name */
  435.     EXPSTR *val_str = init_estr(40);    /* string for "=" and value */
  436.  
  437.     DAV(fprintf(stderr, DHL "   set attr %s\n", varname));
  438.  
  439.     /* append attribute name to attr_str */
  440.     if (hp->compact)
  441.     {
  442.         app_estr(attr_str, compactWs(hp, infgetcws(inpf)));
  443.     }
  444.     else
  445.     {
  446.         app_estr(attr_str, infgetcws(inpf));
  447.     }
  448.     app_estr(attr_str, infgetcw(inpf));
  449.  
  450.     if (!var)
  451.     {
  452.         /* attribute not found: assign to dummy-attribute */
  453.         var = &skipvar;
  454.         var->name = varname;
  455.         var->deftext = NULL;
  456.         var->text = NULL;
  457.         var->enumstr = NULL;
  458.         var->vartype = VT_STRING;
  459.         var->varflag = 0;
  460.  
  461.         /* message: unknown attribute */
  462.         if (!unknown)
  463.             hsc_msg_unkn_attr(hp, varname);
  464.     }
  465.  
  466.     /* get argument */
  467.     nw = infgetw(inpf);
  468.     if (nw)
  469.         if (!strcmp(nw, "="))
  470.         {
  471.             /* append "=" to log */
  472.             if (!hp->compact)
  473.             {
  474.                 app_estr(val_str, infgetcws(inpf));
  475.             }
  476.             app_estr(val_str, infgetcw(inpf));
  477.  
  478.             /* parse expression */
  479.             arg = eval_expression(hp, var, NULL);
  480.  
  481.             /* append value to log */
  482.             if (var->quote != VQ_NO_QUOTE)
  483.                 app_estrch(val_str, var->quote);
  484.             if (get_vartext(var))
  485.                 app_estr(val_str, get_vartext(var));
  486.             if (var->quote != VQ_NO_QUOTE)
  487.                 app_estrch(val_str, var->quote);
  488.  
  489.             if (arg)
  490.             {
  491.                 DAV(fprintf(stderr, DHL "  `%s'\n", arg));
  492.                 ok = TRUE;
  493.             }
  494.         }
  495.         else if (!strcmp(nw, "?"))
  496.         {
  497.             /* process "?="-assignment */
  498.             if (!hp->compact)
  499.                 app_estr(val_str, infgetcws(inpf));
  500.             if (parse_eq(hp))
  501.             {
  502.                 app_estr(val_str, "=");
  503.  
  504.                 arg = eval_cloneattr(hp, var);
  505.  
  506.                 /* append value to log */
  507.                 if (var->quote != VQ_NO_QUOTE)
  508.                     app_estrch(val_str, var->quote);
  509.                 if (get_vartext(var))
  510.                     app_estr(val_str, get_vartext(var));
  511.                 if (var->quote != VQ_NO_QUOTE)
  512.                     app_estrch(val_str, var->quote);
  513.  
  514.                 if (arg)
  515.                 {
  516.                     DAV(fprintf(stderr, DHL "  inherited `%s'\n", arg));
  517.                 }
  518.                 else
  519.                 {
  520.                     DAV(fprintf(stderr, DHL "  inheritage failed\n"));
  521.                     inheritage_failed = TRUE;
  522.                 }
  523.                 ok = TRUE;
  524.             }
  525.         }
  526.         else
  527.         {
  528.             /* handle boolean attribute */
  529.             arg = NULL;
  530.             inungetcwws(inpf);
  531.             if (var == &skipvar)
  532.                 var->vartype = VT_BOOL;
  533.             ok = TRUE;
  534.         }
  535.     else
  536.         hsc_msg_eof(hp, "read attribute value");
  537.  
  538.     if (ok)
  539.         if (arg)
  540.         {
  541.             if (var->vartype == VT_BOOL)
  542.             {
  543.                 /* set boolean attribute depending on expression */
  544.                 set_varbool(var, get_varbool(var));
  545.  
  546.                 /* if the expression returned FALSE, remove
  547.                  * the boolean  switch from tag-call
  548.                  */
  549.                 if (!get_varbool(var))
  550.                     clr_estr(attr_str);
  551.             }
  552.             else if (!inheritage_failed)
  553.                 /* append value to attribute string */
  554.                 estrcat(attr_str, val_str);
  555.         }
  556.         else if (inheritage_failed)
  557.         {
  558.             /* if attribute to inherit from was empty,
  559.              * remove the attribute from tag-call
  560.              */
  561.             clr_estr(attr_str);
  562.         }
  563.         else
  564.         {
  565.             /* no value has been passed to the attribute */
  566.             if (var->vartype == VT_BOOL)
  567.             {
  568.                 /* for boolean attributes, this is legal,
  569.                  * and enables the attribute
  570.                  */
  571.                 set_varbool(var, TRUE);
  572.             }
  573.             else if (!unknown)
  574.             {
  575.                 /* for non-boolean attributes, display
  576.                  * error message
  577.                  */
  578.                 hsc_message(hp, MSG_NOARG_ATTR,
  579.                             "missing value for %A", var);
  580.             }
  581.         }
  582.  
  583.     /* cleanup pseudo-attr */
  584.     if (var == &skipvar)
  585.         clr_vartext(var);
  586.  
  587.     /* append & cleanup attribute and value string */
  588.     app_estr(hp->tag_attr_str, estr2str(attr_str));
  589.     del_estr(attr_str);
  590.     del_estr(val_str);
  591.  
  592.     return (ok);
  593. }
  594.  
  595. /*
  596.  * set_tag_args
  597.  *
  598.  * parse & set all arguments of a tag
  599.  */
  600. ULONG set_tag_args(HSCPRC * hp, HSCTAG * tag)
  601. {
  602.     INFILE *inpf = hp->inpf;
  603.     BOOL ok = FALSE;
  604.     DLLIST *varlist;
  605.     ULONG result_tci = get_mci(hp);     /* resulting tag_call_id */
  606.     STRPTR nw = infgetw(inpf);
  607.  
  608.     /* evaluate which varlist to use */
  609.     varlist = tag->attr;
  610.  
  611.     /* clear string that logs all attributes passed to tag */
  612.     clr_estr(hp->tag_attr_str);
  613.  
  614.     /* read args */
  615.     do
  616.     {
  617.         if (!nw)
  618.             hsc_msg_eof(hp, "read attributes");
  619.         else
  620.         {
  621.             /*
  622.              * process next attribute
  623.              */
  624.             if (!strcmp(nw, ">"))
  625.             {
  626.                 nw = NULL;
  627.                 ok = TRUE;
  628.             }
  629.             else
  630.             {
  631.                 /* process attribute */
  632.                 if (check_attrname(hp, nw))
  633.                 {
  634.                     BOOL unknown = tag->option & HT_UNKNOWN;
  635.                     set_tag_arg(hp, varlist, nw, unknown);
  636.                 }
  637.                 else
  638.                 {
  639.                     /* append empty value */
  640. #if 0
  641.                     app_estr(hp->tag_attr_str, "\"\"");
  642.                     skip_until_eot(hp, NULL);
  643. #endif
  644.                     nw = NULL;
  645.                 }
  646.  
  647.                 /* read next attribute */
  648.                 if (nw)
  649.                     nw = infgetw(inpf);
  650.             }
  651.         }
  652.     }
  653.     while (nw);
  654.  
  655.     /* unset scope */
  656.     unget_mci(hp);
  657.  
  658.     /* set all undefined bool. attr to FALSE */
  659.     clr_varlist_bool(varlist);
  660.  
  661.     /* check for required attributes */
  662.     if (ok)
  663.     {
  664.         ok = check_varlist(hp, varlist);
  665.         if (!ok)
  666.             inungetcw(inpf);
  667.     }
  668.  
  669.     if (!ok)
  670.         result_tci = MCI_ERROR;
  671.  
  672.     return (result_tci);
  673. }
  674.  
  675.